
#ifndef WINDOW_H_
#define WINDOW_H_

#include "Core.h"
#include "Aabb2.h"
#include "RenderTypes.h"

namespace p2 {

class Window;
class WindowCreateStruct
{
public:
	typedef void (*FnOnLButtonDown)(Window& win, int32 x, int32 y);
	typedef void (*FnOnLButtonUp)(Window& win, int32 x, int32 y);
	typedef void (*FnOnRButtonDown)(Window& win, int32 x, int32 y);
	typedef void (*FnOnRButtonUp)(Window& win, int32 x, int32 y);
	typedef void (*FnOnKeyDown)(Window& win, int32 k);
	typedef void (*FnOnKeyUp)(Window& win, int32 k);
	typedef void (*FnOnCursorMove)(Window& win, int32 x, int32 y);

public:
	WindowCreateStruct()
	:
		_onLButtonDown(NULL), _onLButtonUp(NULL),
		_onRButtonDown(NULL), _onRButtonUp(NULL),
		_onKeyDown(NULL), _onKeyUp(NULL),
		_onCursorMove(NULL),
		_name(),
		_worldBound(), _winX(0), _winY(0), _winW(0), _winH(0),
		_unique(NULL), _fullscreen(false)
	{
	}
	WindowCreateStruct(WindowCreateStruct const& cd)
	:
		_onLButtonDown(cd._onLButtonDown), _onLButtonUp(cd._onLButtonUp),
		_onRButtonDown(cd._onRButtonDown), _onRButtonUp(cd._onRButtonUp),
		_onKeyDown(cd._onKeyDown), _onKeyUp(cd._onKeyUp),
		_onCursorMove(cd._onCursorMove),
		_name(cd._name),
		_worldBound(cd._worldBound), _winX(cd._winX), _winY(cd._winY),
		_winW(cd._winW), _winH(cd._winH), _unique(cd._unique),
		_fullscreen(cd._fullscreen)
	{
	}

public:
	FnOnLButtonDown _onLButtonDown;
	FnOnLButtonUp _onLButtonUp;
	FnOnRButtonDown _onRButtonDown;
	FnOnRButtonUp _onRButtonUp;
	FnOnKeyDown _onKeyDown;
	FnOnKeyUp _onKeyUp;
	FnOnCursorMove _onCursorMove;
	String _name;
	Aabb2<real> _worldBound;
	uint32 _winX, _winY;
	uint32 _winW, _winH;
	char const* _unique;
	bool _fullscreen;
};

class Window
{
public:
	virtual ~Window();

	virtual int32 create() = 0;
	virtual void show(bool show = true) const = 0;
	virtual Vector2<real> getCursorPosition() const = 0;
	virtual void swapBuffers() const = 0;
	virtual int32 processContinue() = 0; // return 0 == exit processed

	inline void setViewport(int32 x, int32 y, int32 w, int32 h) const;
	inline void getViewport(int32& x, int32& y, int32& w, int32& h) const;

protected:
	inline Window(WindowCreateStruct const& cs);

private:
	Window();

public:
	WindowCreateStruct _cs;
	int32 _bpp;
	int32 _depthBits;
	bool _rgba;
};

inline Window::Window(WindowCreateStruct const& cd)
	: _cs(cd), _bpp(8), _depthBits(16), _rgba(true)
{
}

inline void Window::setViewport(int32 x, int32 y, int32 w, int32 h) const
{
	::glViewport(x, y, w, h);
}

inline void Window::getViewport(int32& x, int32& y, int32& w, int32& h) const
{
	int32 view[4];
	::glGetIntegerv(GL_VIEWPORT, view);
	x = view[0];
	y = view[1];
	w = view[2];
	h = view[3];
}

}

#endif	//WINDOW_H_
